
            <!DOCTYPE html>
            <html lang="en">
            <head>
                <meta charset="UTF-8">
                <title>K8s中的external-traffic-policy是什么？</title>
            </head>
            <body>
            <a href="https://andyoung.blog.csdn.net">原作者博客</a>
            <div id="content_views" class="markdown_views prism-atom-one-light">
                    <svg xmlns="http://www.w3.org/2000/svg" style="display: none;">
                        <path stroke-linecap="round" d="M5,0 0,2.5 5,5z" id="raphael-marker-block" style="-webkit-tap-highlight-color: rgba(0, 0, 0, 0);"></path>
                    </svg>
                    <blockquote> 
 <p>【摘要】 external-traffic-policy，顾名思义“外部流量策略”，那这个配置有什么作用呢？以及external是指什么东西的外部呢，集群、节点、Pod？今天我们就来学习一下这个概念吧。</p> 
</blockquote> 
<h2><a id="1___externaltrafficpolicy_2"></a>1 什么是external-traffic-policy</h2> 
<p>在k8s的Service对象（申明一条访问通道）中，有一个“externalTrafficPolicy”字段可以设置。有2个值可以设置：Cluster或者Local。</p> 
<p>1）Cluster表示：流量可以转发到其他节点上的Pod。</p> 
<p>2）Local表示：流量只发给本机的Pod。</p> 
<p>图示一下：</p> 
<p><img src="https://i-blog.csdnimg.cn/blog_migrate/5c431c8e8586aae9379c268ae5dfbf81.png" alt="img"></p> 
<h2><a id="2___2_14"></a>2 这2种模式有什么区别</h2> 
<p>存在这2种模式的原因就是，当前节点的Kube-proxy在转发报文的时候，会不会保留原始访问者的IP。</p> 
<h3><a id="21___1Cluster_18"></a>2.1 选择（1）Cluster</h3> 
<p>注：这个是默认模式，Kube-proxy不管容器实例在哪，公平转发。</p> 
<p>Kube-proxy转发时会替换掉报文的源IP。即：容器收的报文，源IP地址，已经被替换为上一个转发节点的了。</p> 
<p><img src="https://i-blog.csdnimg.cn/blog_migrate/226657b7bd58396719f818b741c0ed81.png" alt="img"></p> 
<p>原因是Kube-proxy在做转发的时候，会做一次SNAT (source network address translation)，所以源IP变成了节点1的IP地址。</p> 
<p>ps：snat确保回去的报文可以原路返回，不然回去的路径不一样，客户会认为非法报文的。（我发给张三的，怎么李四给我回应？丢弃！）</p> 
<p>这种模式好处是负载均衡会比较好，因为无论容器实例怎么分布在多个节点上，它都会转发过去。当然，由于多了一次转发，性能会损失一丢丢。</p> 
<h3><a id="22___2Local_32"></a>2.2 选择（2）Local</h3> 
<p>这种情况下，只转发给本机的容器，绝不跨节点转发。</p> 
<p>Kube-proxy转发时会保留源IP。即：容器收到的报文，看到源IP地址还是用户的。</p> 
<p><img src="https://i-blog.csdnimg.cn/blog_migrate/316c07f1e14a29841a5a8d8ffa43d5f0.png" alt="img"></p> 
<p>缺点是负载均衡可能不是很好，因为一旦容器实例分布在多个节点上，它只转发给本机，不跨节点转发流量。当然，少了一次转发，性能会相对好一丢丢。</p> 
<p>注：这种模式下的Service类型只能为外部流量，即：LoadBalancer 或者 NodePort 两种，否则会报错。</p> 
<p>同时，由于本机不会跨节点转发报文，所以要想所有节点上的容器有负载均衡，就需要上一级的Loadbalancer来做了。</p> 
<p><img src="https://i-blog.csdnimg.cn/blog_migrate/3cddee7aa54707d26465ad34c8dcc653.png" alt="img"></p> 
<p>不过流量还是会不太均衡，如上图，Loadbalancer看到的是2个后端（把节点的IP），每个Node上面几个Pod对Loadbalancer来说是不知道的。</p> 
<p>想要解决负载不均衡的问题：可以给Pod容器设置反亲和，让这些容器平均的分布在各个节点上（不要聚在一起）。</p> 
<pre><code class="prism language-javascript">affinity<span class="token operator">:</span>
  podAntiAffinity<span class="token operator">:</span>
    preferredDuringSchedulingIgnoredDuringExecution<span class="token operator">:</span>
    <span class="token operator">-</span> weight<span class="token operator">:</span> <span class="token number">100</span>
      podAffinityTerm<span class="token operator">:</span>
        labelSelector<span class="token operator">:</span>
          matchExpressions<span class="token operator">:</span>
           <span class="token operator">-</span> key<span class="token operator">:</span> k8s<span class="token operator">-</span>app
             operator<span class="token operator">:</span> In
             values<span class="token operator">:</span>
             <span class="token operator">-</span> my<span class="token operator">-</span>app
        topologyKey<span class="token operator">:</span> kubernetes<span class="token punctuation">.</span>io<span class="token operator">/</span>hostname
</code></pre> 
<p>像下面这样，负载均衡情况就会好很多~</p> 
<p><img src="https://i-blog.csdnimg.cn/blog_migrate/5560524212df8dba6c1a397a2712c53c.png" alt="img"></p> 
<h2><a id="3____71"></a>3 两种模式该怎么选</h2> 
<p>要想性能（时延）好，当然应该选 Local 模式喽，毕竟流量转发少一次SNAT嘛。</p> 
<p>不过注意，选了这个就得考虑好怎么处理好负载均衡问题（ps：通常我们使用Pod间反亲和来达成）。</p> 
<p>如果你是从外部LB接收流量的，那么使用：Local模式 + Pod反亲和，一般是足够的。</p>
                </div>
            </body>
            </html>
            